import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
from matplotlib.patches import Circle
from datetime import datetime

# ---------------------- 1. 基础配置（路径+样式） ----------------------
ROOT_DIR = r"D:\大三上\大数据分析及数据可视化\《Excel数据可视化 - 从图表到数据大屏》-清华-郭宏远\实验"
DATA_PATH = os.path.join(ROOT_DIR, "erp_order_data.xlsx")
RESULTS_DIR = os.path.join(ROOT_DIR, "results")
os.makedirs(RESULTS_DIR, exist_ok=True)
SAVE_PATH = os.path.join(RESULTS_DIR, "16_波浪水球图.png")

plt.rcParams.update({
    'font.sans-serif': ['SimHei'],
    'axes.unicode_minus': False,
    'axes.facecolor': '#1A1A2E',  # 深蓝色背景
    'text.color': 'white',  # 白色字体
    'axes.labelcolor': 'white',
    'xtick.color': 'white',
    'ytick.color': 'white',
    'grid.color': '#BFBFBF',
    'grid.linewidth': 1.2,
    'grid.alpha': 0.2
})

# ---------------------- 2. 数据读取与处理 ----------------------
try:
    df = pd.read_excel(DATA_PATH)
    print(f"✓ 数据加载成功: {DATA_PATH}")
except Exception as e:
    print(f"数据加载失败: {e}")
    # 创建模拟数据作为备用
    print("使用模拟数据创建水球图...")
    completion_rate = 0.65
    latest_date_str = "2025-10-15"
else:
    # 确保订单时间是datetime类型
    if 'order_time' in df.columns:
        df['order_time'] = pd.to_datetime(df['order_time'])
        latest_date = df['order_time'].max()
        latest_date_str = latest_date.strftime('%Y-%m-%d')
    else:
        latest_date_str = "2025-10-15"

    # 计算订单完成率 - 将"已完成"状态的订单视为完成
    if 'status' in df.columns:
        total_orders = len(df)
        completed_orders = len(df[df['status'] == '已完成'])
        completion_rate = completed_orders / total_orders if total_orders > 0 else 0.65
    else:
        # 没有状态列，使用支付金额与应付金额的比率
        if 'paid_amount' in df.columns and 'payable_amount' in df.columns:
            actual_payment = df['paid_amount'].sum()
            expected_payment = df['payable_amount'].sum()
            completion_rate = actual_payment / expected_payment if expected_payment > 0 else 0.65
        else:
            completion_rate = 0.65  # 默认值

    print(f"总订单数: {total_orders}")
    print(f"已完成订单数: {completed_orders}")
    print(f"订单完成率: {completion_rate:.2%}")

# 确保完成率在0-1之间
completion_rate = max(0, min(1, completion_rate))

# ---------------------- 3. 绘制水球图 ----------------------
fig, ax = plt.subplots(figsize=(14, 9))
ax.set_aspect('equal')

# 定义颜色
water_color = '#4BB5C2'  # 水色（青蓝色）
background_color = '#1A1A2E'  # 背景色（深蓝）
border_color = '#E0E0E0'  # 边框色
text_color = 'white'  # 文字色

# 大圆边框
outer_circle = Circle((0.5, 0.5), 0.4, color=background_color, ec=border_color, lw=3, alpha=0.8)
ax.add_patch(outer_circle)

# 水位高度
water_level = 1 - completion_rate  # 从底部开始填充

# 生成x坐标
x = np.linspace(0.1, 0.9, 200)
# 计算圆的上下边界
circle_center_x, circle_center_y = 0.5, 0.5
circle_radius = 0.4

# 计算水的波浪效果
wave_amplitude = 0.02
wave_frequency = 10
wave_offset = water_level * circle_radius + circle_center_y - wave_amplitude

# 生成波浪水面
y_wave = wave_offset + wave_amplitude * np.sin(wave_frequency * (x - 0.5) * np.pi)

# 计算圆的边界
y_upper = circle_center_y + np.sqrt(np.maximum(0, circle_radius ** 2 - (x - circle_center_x) ** 2))
y_lower = circle_center_y - np.sqrt(np.maximum(0, circle_radius ** 2 - (x - circle_center_x) ** 2))

# 构建水的填充区域
verts = []
# 底部沿圆
for xi in x:
    verts.append((xi, y_lower[np.abs(x - xi).argmin()]))
# 顶部沿波浪（从右到左）
for xi in x[::-1]:
    # 水面高度不能超出圆的边界
    wave_y = min(y_wave[np.abs(x - xi).argmin()], y_upper[np.abs(x - xi).argmin()])
    verts.append((xi, wave_y))

from matplotlib.patches import Polygon

water_patch = Polygon(verts, closed=True, color=water_color, alpha=0.8, ec=water_color, lw=1)
ax.add_patch(water_patch)

# 添加波浪效果
for i in range(3):
    wave_offset_i = wave_offset + i * 0.02
    y_wave_i = wave_offset_i + wave_amplitude * np.sin(wave_frequency * (x - 0.5) * np.pi + i * 1.5)
    wave_x = []
    wave_y = []
    for xi in x:
        # 限制波浪在圆内
        dist = np.sqrt((xi - circle_center_x) ** 2 + (wave_offset_i - circle_center_y) ** 2)
        if dist <= circle_radius:
            wave_x.append(xi)
            wave_y.append(min(y_wave_i[np.abs(x - xi).argmin()],
                              circle_center_y + np.sqrt(circle_radius ** 2 - (xi - circle_center_x) ** 2)))

    if wave_x:
        ax.plot(wave_x, wave_y, color=water_color, alpha=0.5 - i * 0.15, linewidth=1)

# 高光效果
highlight_center_x = circle_center_x - 0.1
highlight_center_y = circle_center_y - 0.1
highlight_radius = circle_radius * 0.8
highlight_circle = Circle((highlight_center_x, highlight_center_y), highlight_radius,
                          color='white', alpha=0.1, ec='none')
ax.add_patch(highlight_circle)

# 中心文字 - 百分比
percentage_text = f'{completion_rate:.0%}'
ax.text(0.5, 0.55, percentage_text, fontsize=50, fontweight='bold',
        ha='center', va='center', color=text_color)

# 标题文字
ax.text(0.5, 0.35, '订单完成率', fontsize=16, color=text_color,
        ha='center', va='center')

# 顶部标题
title_text = f'2025年上半年目标完成率'
subtitle_text = f'截至{latest_date_str}，销售目标总体完成率达到{completion_rate:.0%}'
ax.set_title(f'{title_text}\n{subtitle_text}', fontsize=20, fontweight='bold', pad=30,
             color=text_color)

# 隐藏坐标轴
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.axis('off')

# 底部说明
fig.text(0.5, 0.02,
         '*注：数据来源于公司销售系统',
         ha='center', fontsize=10, color='#B0B0B0', alpha=0.7)

plt.tight_layout(rect=[0, 0.05, 1, 0.95])

# 保存
plt.savefig(SAVE_PATH, dpi=300, bbox_inches='tight', facecolor=background_color)
plt.show()

print(f"✅ 水球图生成成功！")
print(f"📁 保存路径：{SAVE_PATH}")
print(f"📊 订单完成率：{completion_rate:.2%}")